package com.demo.lock;

import cn.lingyangwl.framework.lock.annotation.DistributedLock;
import cn.lingyangwl.framework.lock.constant.LockBeanName;
import cn.lingyangwl.framework.lock.manager.ILockManager;
import cn.lingyangwl.framework.lock.model.ILock;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author shenguangyang
 */
@Service
public class GoodService {
    private static final String REDIS_LOCK = "redis_lock";

    @Resource
    private Redisson redisson;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource(name = LockBeanName.REDISSON_SERVICE)
//    @Resource
    private ILockManager lockManager;

    public void buyGoods() {
        RLock lock = redisson.getLock(REDIS_LOCK);
        lock.lock(500, TimeUnit.MILLISECONDS);
        try {
            String obj = stringRedisTemplate.opsForValue().get("good:001");
            // 模拟业务处理时间超过锁时间, 验证锁续命
//            TimeUnit.MILLISECONDS.sleep(RandomUtil.randomInt(1, 600));
            int stock = obj != null ? Integer.parseInt(obj) : 0;
            if (stock > 0) {
                stringRedisTemplate.opsForValue().set("good:001", String.valueOf(stock - 1));
                Console.log("当前商品剩余数量: {}", stock);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 测试 LockService 服务实现的分布式锁功能,
     */
    public void buyGoodsByLockServiceWay() {
        ILock lock = lockManager.getLock(REDIS_LOCK);
        lock.tryLock(500, TimeUnit.MILLISECONDS);
        try {
            String obj = stringRedisTemplate.opsForValue().get("good:001");
            // 模拟业务处理时间超过锁时间, 验证锁续命
            TimeUnit.MILLISECONDS.sleep(RandomUtil.randomInt(1, 20));
            int stock = obj != null ? Integer.parseInt(obj) : 0;
            if (stock > 0) {
                stringRedisTemplate.opsForValue().set("good:001", String.valueOf(stock - 1));
                Console.log("当前商品剩余数量: {}", stock);
            } else {
                System.err.println("商品库存为空");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 测试 通过注解实现分布式锁
     */
    @DistributedLock(beanName = LockBeanName.REDISSON_SERVICE, lockKey = "/lock")
    public void buyGoodsByAnnotationWay() throws InterruptedException {
        String obj = stringRedisTemplate.opsForValue().get("good:001");
        // 模拟业务处理时间超过锁时间, 验证锁续命
        TimeUnit.MILLISECONDS.sleep(RandomUtil.randomInt(1, 20));
        int stock = obj != null ? Integer.parseInt(obj) : 0;
        if (stock > 0) {
            stringRedisTemplate.opsForValue().set("good:001", String.valueOf(stock - 1));
            Console.log("当前商品剩余数量: {}", stock);
        }
    }
}
